fix: make submodule.update() after submodule.deinit() work#2175
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes Submodule.update() so that a submodule can be re-initialized via GitPython after it was deinitialized with git submodule deinit, by reusing the retained repository under the parent repo’s .git/modules/ rather than attempting a fresh clone.
Changes:
- Detect and reuse an existing retained submodule repository under
.git/modules/when the worktree checkout is missing. - Recreate the submodule checkout by restoring the
.gitfile + modulecore.worktreeconfig and resetting to repopulate index/worktree. - Add test coverage to validate update-after-deinit behavior (including
init=False,dry_run=True, and nested submodule names).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
git/objects/submodule/base.py |
Adds a “reconnect retained repo” path in Submodule.update() to restore a deinitialized checkout without recloning. |
test/test_submodule.py |
Adds tests covering submodule.update() behavior after submodule.deinit() across several modes and a nested submodule case. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
72895f4 to
eb7bf7b
Compare
Git's `submodule deinit` command removes the submodule checkout but retains its repository under the parent repository's `.git/modules` directory. Submodule.update() previously treated the missing checkout as a completely uninitialized submodule and attempted to clone it again. The clone could not reuse the existing module repository, preventing a deinitialized submodule from being initialized again through GitPython. Detect a valid retained repository before entering the clone path. Restore the checkout's `.git` file and the module repository's worktree configuration, reset the retained repository to recreate its index and working tree, and restore the submodule URL in the parent configuration. Continue using the existing clone behavior when no valid retained repository is available. Co-authored-by: Sebastian Thiel <[email protected]>
eb7bf7b to
b9d82c0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Git's
submodule deinitcommand removes the submodule checkout but retains its repository under the parent repository's.git/modulesdirectory.Submodule.update() previously treated the missing checkout as a completely uninitialized submodule and attempted to clone it again. The clone could not reuse the existing module repository, preventing a deinitialized submodule from being initialized again through GitPython.
Detect a valid retained repository before entering the clone path. Restore the checkout's
.gitfile and the module repository's worktree configuration, reset the retained repository to recreate its index and working tree, and restore the submodule URL in the parent configuration. Continue using the existing clone behavior when no valid retained repository is available.Tasks